home *** CD-ROM | disk | FTP | other *** search
/ Adobe Graphics & Publishing SDK 1996 December / Adobe Graphics & Publishing SDK 1996 December.iso / pc / ps40sdk / examples / common / sources.c / piutilities.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  37.1 KB  |  1,630 lines

  1. /*
  2.     File: PIUtilities.c
  3.     
  4.     Copyright (c) 1993-6, Adobe Systems Incorporated.
  5.     All rights reserved.
  6.     
  7.     C source file for plug-in callback utilities.
  8. */
  9.  
  10. #include "PIUtilities.h"
  11.  
  12. /*****************************************************************************/
  13. /* Returns a handle to the current window or NULL. */
  14.  
  15. Handle HostGetPlatformWindowPtr (AboutRecordPtr aboutPtr)
  16. {
  17.     PlatformData *platform = (PlatformData *) (aboutPtr->platformData);
  18.     #if MSWindows
  19.     return (Handle)platform->hwnd;
  20.     #else
  21.     return NULL;
  22.     #endif
  23. }
  24. /*****************************************************************************/
  25.  
  26. Boolean HostDisplayPixelsAvailable (DisplayPixelsProc proc)
  27. {
  28.     Boolean    available = TRUE;
  29.     
  30.     if (!proc)
  31.         available = FALSE;
  32.     
  33.     return available;
  34. }
  35. /*****************************************************************************/
  36.  
  37. Boolean WarnHostDisplayPixelsAvailable (DisplayPixelsProc proc,
  38.                                         Handle hDllInstance)
  39. {
  40.     
  41.     Boolean available = HostDisplayPixelsAvailable(proc);
  42.     Str255 s = "";
  43.     
  44.     if (!available)
  45.     {
  46.         DoubleToString(2.502, s, 3);
  47.         s[ s[0]-1 ] = '.'; // 2.5.2
  48.         
  49.         ShowVersionAlert (hDllInstance,
  50.                           NULL,
  51.                           AlertID,
  52.                           kNeedVers,
  53.                           s,
  54.                           NULL);
  55.     }
  56.     return available;
  57.     
  58. }
  59.     
  60. /*****************************************************************************/
  61.  
  62. Boolean HostAdvanceStateAvailable (AdvanceStateProc proc)
  63. {
  64.     Boolean    available = TRUE;
  65.     
  66.     if (!proc)
  67.         available = FALSE;
  68.     
  69.     return available;
  70. }
  71. /*****************************************************************************/
  72.  
  73. Boolean WarnHostAdvanceStateAvailable (AdvanceStateProc proc,
  74.                                        Handle hDllInstance)
  75. {
  76.     Boolean available = HostAdvanceStateAvailable(proc);
  77.     Str255    s = "";
  78.     
  79.     if (!available)
  80.     {
  81.         DoubleToString(3.0, s, 1);
  82.     
  83.         ShowVersionAlert (hDllInstance,
  84.                           NULL,
  85.                           AlertID,
  86.                           kNeedVers,
  87.                           s,
  88.                           NULL);
  89.     }
  90.     return available;
  91. }
  92. /*****************************************************************************/
  93.  
  94. Boolean HostColorServicesAvailable (ColorServicesProc proc)
  95. {
  96.     Boolean    available = TRUE;
  97.     
  98.     if (!proc)
  99.         available = FALSE;
  100.     
  101.     return available;
  102. }
  103. /*****************************************************************************/
  104.  
  105. Boolean WarnHostColorServicesAvailable (ColorServicesProc proc,
  106.                                         Handle hDllInstance)
  107. {
  108.     Boolean available = HostColorServicesAvailable(proc);
  109.     Str255    s = "";
  110.     
  111.     if (!available)
  112.     {
  113.         DoubleToString(2.5, s, 1);
  114.     
  115.         ShowVersionAlert (hDllInstance,
  116.                           NULL,
  117.                           AlertID,
  118.                           kNeedVers,
  119.                           s,
  120.                           NULL);
  121.     }
  122.     return available;
  123. }
  124. /*******************************************************************/
  125. /* Sets a standard color array */
  126. void CSSetColor (int16 *color, int16 color1, int16 color2, int16 color3, int16 color4)
  127. {
  128.     color[0] = color1;
  129.     color[1] = color2;
  130.     color[2] = color3;
  131.     color[3] = color4;
  132. }
  133. /*******************************************************************/
  134. /* Copys a color array from color2 -> color1 */
  135. void CSCopyColor (int16 *color1, int16 *color2)
  136. {
  137.     short loop;
  138.     
  139.     for (loop = 0; loop < 4; loop++)
  140.     {
  141.         color1[loop] = color2[loop];
  142.     }
  143. }
  144. /*******************************************************************/
  145. /* Returns number of expected planes for imageMode */
  146. int16 CSPlanesFromMode (int16 imageMode, int16 currPlanes)
  147. {
  148.     switch (imageMode)
  149.     {
  150.         case plugInModeBitmap:
  151.         case plugInModeGrayScale:
  152.         case plugInModeGray16:
  153.         case plugInModeDuotone:
  154.             return 1;
  155.             break;
  156.         case plugInModeIndexedColor:
  157.         case plugInModeRGBColor:
  158.         case plugInModeHSLColor:
  159.         case plugInModeHSBColor:
  160.         case plugInModeLabColor:
  161.         case plugInModeRGB48:
  162.             return 3;
  163.             break;
  164.         case plugInModeCMYKColor:
  165.             return 4;
  166.             break;
  167.         case plugInModeMultichannel:
  168.             return currPlanes;
  169.             break;
  170.     }
  171. }
  172. /*******************************************************************/
  173. /* Maps imageMode to color services space */
  174. int16 CSModeToSpace (int16 imageMode)
  175. {
  176.     switch (imageMode)
  177.     {
  178.         case plugInModeBitmap:
  179.         case plugInModeIndexedColor:
  180.         case plugInModeMultichannel:
  181.             return plugIncolorServicesChosenSpace; // unsupported space
  182.             break;
  183.         case plugInModeGrayScale:
  184.         case plugInModeGray16:
  185.         case plugInModeDuotone:
  186.             return plugIncolorServicesGraySpace;
  187.             break;
  188.         case plugInModeRGBColor:
  189.         case plugInModeRGB48:
  190.             return plugIncolorServicesRGBSpace;
  191.             break;
  192.         case plugInModeHSLColor:
  193.             return plugIncolorServicesHSLSpace;
  194.             break;
  195.         case plugInModeHSBColor:
  196.             return plugIncolorServicesHSBSpace;
  197.             break;
  198.         case plugInModeLabColor:
  199.             return plugIncolorServicesLabSpace;
  200.             break;
  201.         case plugInModeCMYKColor:
  202.             return plugIncolorServicesCMYKSpace;
  203.             break;
  204.     }
  205. }
  206. /*******************************************************************/
  207. OSErr HostCSConvertColor (ColorServicesProc proc,
  208.                          int16 sourceSpace,
  209.                          int16 resultSpace,
  210.                          int16 *color)
  211. {
  212.     OSErr    gotErr = noErr;
  213.     ColorServicesInfo    csinfo;
  214.     
  215.     if (HostColorServicesAvailable(proc))
  216.     { // now populate color services info with stuff
  217.         csinfo.selector = plugIncolorServicesConvertColor;
  218.         csinfo.sourceSpace = sourceSpace;
  219.         csinfo.resultSpace = resultSpace;
  220.         csinfo.reservedSourceSpaceInfo = NULL; // must be null
  221.         csinfo.reservedResultSpaceInfo = NULL; // must be null
  222.         CSCopyColor(&csinfo.colorComponents[0], color);
  223.         csinfo.reserved = NULL; // must be null
  224.         csinfo.selectorParameter.pickerPrompt = NULL; // not needed
  225.         csinfo.infoSize = sizeof(csinfo);
  226.         gotErr = (*(proc)) (&csinfo);
  227.         CSCopyColor (color, &csinfo.colorComponents[0]);
  228.     } // otherwise return noErr with original components intact
  229.     return gotErr;
  230. }
  231. /*****************************************************************************/
  232. Boolean HostBufferProcsAvailable (BufferProcs *procs, Boolean *tooNew)
  233.     {
  234.     
  235.     Boolean available = TRUE;
  236.     Boolean myTooNew = FALSE;
  237.     
  238.     if (!procs)
  239.         available = FALSE;
  240.         
  241.     else if (procs->bufferProcsVersion < kCurrentBufferProcsVersion)
  242.         available = FALSE;
  243.         
  244.     else if (procs->bufferProcsVersion > kCurrentBufferProcsVersion)
  245.     {    
  246.         available = FALSE;
  247.         myTooNew = TRUE;    
  248.     }
  249.         
  250.     else if (procs->numBufferProcs < kCurrentBufferProcsCount ||
  251.              !procs->allocateProc ||
  252.              !procs->lockProc ||
  253.              !procs->unlockProc ||
  254.              !procs->freeProc ||
  255.              !procs->spaceProc)
  256.         available = FALSE;
  257.         
  258.     if (tooNew)
  259.         *tooNew = myTooNew;
  260.         
  261.     return available;
  262.     
  263.     }
  264. /*****************************************************************************/
  265. Boolean WarnHostBufferProcsAvailable (BufferProcs *procs,
  266.                                       Handle hDllInstance)
  267. {
  268.     
  269.     Boolean available, tooNew;
  270.     Str255 s = "";
  271.     
  272.     available = HostBufferProcsAvailable (procs, &tooNew);
  273.     
  274.     if (!available)
  275.     {
  276.         DoubleToString(2.5, s, 1);
  277.         
  278.         ShowVersionAlert (hDllInstance,
  279.                           NULL,
  280.                           AlertID,
  281.                           (short)(tooNew ? kWrongHost : kNeedVers),
  282.                           s,
  283.                           NULL);
  284.     }        
  285.     return available;
  286. }
  287. /*****************************************************************************/
  288. int32 HostBufferSpace (BufferProcs *procs)
  289.     {
  290.     
  291.     if (!HostBufferProcsAvailable (procs, NULL))
  292.         return 0;    
  293.     else
  294.         return (*procs->spaceProc) ();
  295.     
  296.     }
  297. /*****************************************************************************/
  298. OSErr HostAllocateBuffer (BufferProcs *procs, int32 size, BufferID *bufferID)
  299.     {
  300.     
  301.     *bufferID = 0;
  302.     
  303.     if (!HostBufferProcsAvailable (procs, NULL))
  304.         return memFullErr;
  305.         
  306.     else
  307.         return (*procs->allocateProc) (size, bufferID);
  308.     
  309.     }
  310. /*****************************************************************************/
  311. void HostFreeBuffer (BufferProcs *procs, BufferID bufferID)
  312.     {
  313.     
  314.     if (HostBufferProcsAvailable (procs, NULL))
  315.         (*procs->freeProc) (bufferID);
  316.     
  317.     }
  318. /*****************************************************************************/
  319. Ptr HostLockBuffer (BufferProcs *procs, BufferID bufferID, Boolean moveHigh)
  320.     {
  321.     
  322.     if (HostBufferProcsAvailable (procs, NULL))
  323.         return (*procs->lockProc) (bufferID, moveHigh);
  324.     else
  325.         return NULL;
  326.     
  327.     }
  328. /*****************************************************************************/
  329. void HostUnlockBuffer (BufferProcs *procs, BufferID bufferID)
  330.     {
  331.     
  332.     if (HostBufferProcsAvailable (procs, NULL))
  333.         (*procs->unlockProc) (bufferID);
  334.     
  335.     }
  336. /*****************************************************************************/
  337. OSErr HostAllocateStripBuffer (BufferProcs *procs,
  338.                                int32 rowBytes,
  339.                                int16 minHeight,
  340.                                int16 maxHeight,
  341.                                int16 numBuffers,
  342.                                int16 *actualHeight,
  343.                                BufferID *bufferID)
  344.     {
  345.     
  346.     int16 curHeight;
  347.     int32 curSize;
  348.     OSErr curResult = noErr;
  349.     int32 availableSpace = HostBufferSpace (procs) / numBuffers;
  350.     
  351.     int32 availableHeight = availableSpace / rowBytes;
  352.     
  353.     curHeight = (availableHeight < maxHeight) ? (int16) availableHeight
  354.                                               : maxHeight;
  355.                                               
  356.     ++curHeight;
  357.     
  358.     curSize = rowBytes * (int32) curHeight;
  359.     
  360.     *bufferID = 0;
  361.     
  362.     while (!*bufferID && curHeight > minHeight)
  363.         {
  364.         
  365.         --curHeight;
  366.         curSize -= rowBytes;
  367.         
  368.         curResult = HostAllocateBuffer (procs, curSize, bufferID);
  369.         
  370.         }
  371.         
  372.     if (*bufferID)
  373.         *actualHeight = curHeight;
  374.         
  375.     return curResult;
  376.     
  377.     }
  378. /*****************************************************************************/
  379. Boolean HostResourceProcsAvailable (ResourceProcs *procs, Boolean *tooNew)
  380.     {
  381.     
  382.     Boolean available = TRUE;
  383.     Boolean myTooNew = FALSE;
  384.     
  385.     if (!procs)
  386.         available = FALSE;
  387.         
  388.     else if (procs->resourceProcsVersion < kCurrentResourceProcsVersion)
  389.         available = FALSE;
  390.         
  391.     else if (procs->resourceProcsVersion > kCurrentResourceProcsVersion)
  392.         {
  393.         
  394.         available = FALSE;
  395.         
  396.         myTooNew = TRUE;
  397.         
  398.         }
  399.         
  400.     else if (procs->numResourceProcs < kCurrentResourceProcsCount ||
  401.              !procs->countProc ||
  402.              !procs->getProc ||
  403.              !procs->deleteProc ||
  404.              !procs->addProc)
  405.         available = FALSE;
  406.         
  407.     if (tooNew)
  408.         *tooNew = myTooNew;
  409.         
  410.     return available;
  411.     
  412.     }
  413. /*****************************************************************************/
  414. Boolean WarnHostResourceProcsAvailable (ResourceProcs *procs,
  415.                                         Handle hDllInstance)
  416. {
  417.     
  418.     Boolean available, tooNew;
  419.     Str255 s = "";
  420.     available = HostResourceProcsAvailable (procs, &tooNew);
  421.     
  422.     if (!available)
  423.     {
  424.         DoubleToString(3.0, s, 1);
  425.         ShowVersionAlert (hDllInstance,
  426.                           NULL,
  427.                           AlertID,
  428.                           (short)(tooNew ? kWrongHost : kNeedVers),
  429.                           s,
  430.                           NULL);
  431.     }    
  432.     return available;
  433. }
  434. /*****************************************************************************/
  435. int16 HostCountPIResources (ResourceProcs *procs, ResType type)
  436.     {
  437.     
  438.     if (!HostResourceProcsAvailable (procs, NULL))
  439.         return 0;
  440.         
  441.     else
  442.         return (*procs->countProc) (type);
  443.     
  444.     }
  445. /*****************************************************************************/
  446. Handle HostGetPIResource (ResourceProcs *procs, ResType type, int16 index)
  447.     {
  448.     
  449.     if (!HostResourceProcsAvailable (procs, NULL))
  450.         return NULL;
  451.         
  452.     else
  453.         return (*procs->getProc) (type, index);
  454.     
  455.     }
  456. /*****************************************************************************/
  457. void HostDeletePIResource (ResourceProcs *procs, ResType type, int16 index)
  458.     {
  459.     
  460.     if (HostResourceProcsAvailable (procs, NULL))
  461.         (*procs->deleteProc) (type, index);
  462.     
  463.     }
  464. /*****************************************************************************/
  465. OSErr HostAddPIResource (ResourceProcs *procs, ResType type, Handle data)
  466.     {
  467.     
  468.     if (!HostResourceProcsAvailable (procs, NULL))
  469.         return memFullErr;
  470.         
  471.     else
  472.         return (*procs->addProc) (type, data);
  473.     
  474.     }
  475. /*****************************************************************************/
  476. Boolean HostHandleProcsAvailable (HandleProcs *procs, Boolean *tooNew)
  477.     {
  478.     
  479.     /* We only require the new, dispose, set size, and get size procs. */
  480.     /* Lock and unlock can usually be gotten around without resorting  */
  481.     /* to callbacks.                                                   */
  482.     
  483.     #define kCoreHandleProcsCount 4
  484.     
  485.     Boolean available = TRUE;
  486.     Boolean myTooNew = FALSE;
  487.     
  488.     if (!procs)
  489.         available = FALSE;
  490.         
  491.     else if (procs->handleProcsVersion < kCurrentHandleProcsVersion)
  492.         available = FALSE;
  493.         
  494.     else if (procs->handleProcsVersion > kCurrentHandleProcsVersion)
  495.         {
  496.         
  497.         available = FALSE;
  498.         
  499.         myTooNew = TRUE;
  500.         
  501.         }
  502.         
  503.     else if (procs->numHandleProcs < kCoreHandleProcsCount ||
  504.              !procs->newProc ||
  505.              !procs->disposeProc ||
  506.              !procs->getSizeProc ||
  507.              !procs->setSizeProc)
  508.         available = FALSE;
  509.         
  510.     if (tooNew)
  511.         *tooNew = myTooNew;
  512.         
  513.     return available;
  514.     
  515.     }
  516. /*****************************************************************************/
  517. Boolean WarnHostHandleProcsAvailable (HandleProcs *procs,
  518.                                       Handle hDllInstance)
  519. {
  520.     Boolean available, tooNew;
  521.     Str255 s = "";
  522.     
  523.     available = HostHandleProcsAvailable (procs, &tooNew);
  524.     
  525.     if (!available)
  526.     {
  527.         DoubleToString(3.0, s, 1);
  528.         ShowVersionAlert (hDllInstance,
  529.                           NULL,
  530.                           AlertID,
  531.                           (short)(tooNew ? kWrongHost : kNeedVers),
  532.                           s,
  533.                           NULL);
  534.     }
  535.         
  536.     return available;
  537. }
  538. /*****************************************************************************/
  539. Handle HostNewHandle (HandleProcs *procs, int32 size)
  540.     {
  541.     
  542.     if (!HostHandleProcsAvailable (procs, NULL))
  543.     {
  544. #if Macintosh
  545.         return (Handle)(NewHandle (size));
  546. #else
  547.         return NULL;
  548. #endif
  549.     }
  550.     else
  551.         return (*procs->newProc) (size);
  552.     
  553.     }
  554. /*****************************************************************************/
  555. void HostDisposeHandle (HandleProcs *procs, Handle h)
  556.     {
  557.     
  558.     if (!HostHandleProcsAvailable (procs, NULL))
  559.     {
  560. #if Macintosh
  561.         DisposHandle (h);
  562. #endif
  563.     }
  564.     else
  565.         (*procs->disposeProc) (h);
  566.     
  567.     }
  568. /*****************************************************************************/
  569. int32 HostGetHandleSize (HandleProcs *procs, Handle h)
  570.     {
  571.     
  572.     if (!HostHandleProcsAvailable (procs, NULL))
  573.     {
  574. #if Macintosh
  575.         return GetHandleSize (h);
  576. #else
  577.         return 0;
  578. #endif
  579.     }
  580.     else
  581.         return (*procs->getSizeProc) (h);
  582.     
  583.     }
  584. /*****************************************************************************/
  585. OSErr HostSetHandleSize (HandleProcs *procs, Handle h, int32 newSize)
  586.     {
  587.     
  588.     if (!HostHandleProcsAvailable (procs, NULL))
  589.         {    
  590. #if Macintosh
  591.         SetHandleSize (h, newSize);
  592.         return MemError ();
  593. #else
  594.         return -1;
  595. #endif
  596.         }
  597.         
  598.     else
  599.         return (*procs->setSizeProc) (h, newSize);
  600.     
  601.     }
  602. /*****************************************************************************/
  603. Ptr HostLockHandle (HandleProcs *procs, Handle h, Boolean moveHigh)
  604.     {
  605.     
  606.     if (procs &&
  607.         procs->handleProcsVersion == kCurrentHandleProcsVersion &&
  608.         procs->numHandleProcs >= 6 &&
  609.         procs->lockProc &&
  610.         procs->unlockProc)
  611.         {
  612.         
  613.         return (*procs->lockProc) (h, moveHigh);
  614.         
  615.         }
  616.         
  617.     else
  618.         {
  619.         
  620. #if Macintosh
  621.         if (moveHigh)
  622.             MoveHHi (h);
  623.     
  624.         HLock (h);
  625.         
  626.         return *h;
  627. #else
  628.         return GlobalLock (h);
  629. #endif
  630.         }
  631.     
  632.     }
  633. /*****************************************************************************/
  634. void HostUnlockHandle (HandleProcs *procs, Handle h)
  635.     {
  636.     
  637.     if (procs &&
  638.         procs->handleProcsVersion == kCurrentHandleProcsVersion &&
  639.         procs->numHandleProcs >= 6 &&
  640.         procs->lockProc &&
  641.         procs->unlockProc)
  642.         {
  643.         
  644.         (*procs->unlockProc) (h);
  645.         
  646.         }
  647.         
  648.     else
  649.         {
  650. #if Macintosh    
  651.         HUnlock (h);
  652. #else
  653.         GlobalUnlock (h);
  654. #endif
  655.         }
  656.     
  657.     }
  658. /*****************************************************************************/
  659. void HostHandle2String(HandleProcs *procs, Handle h, Str255 s)
  660. {
  661.     Ptr p = NULL;
  662.     
  663.     s[ (s[0]=0)+1 ] = 0;
  664.     if (h != NULL)
  665.     {
  666.         p = HostLockHandle(procs, h, FALSE);
  667.         if (p != NULL)
  668.         {
  669.             AppendString(s, (unsigned char *)p, 0, (short)HostGetHandleSize(procs, h));
  670.         }
  671.         HostUnlockHandle(procs, h);
  672.     }
  673.     s[ 1+((s[0] > 254) ? 254 : s[0]) ] = 0; // null terminate that puppy!
  674. }
  675.     
  676. /*****************************************************************************/
  677. Handle HostString2Handle(HandleProcs *procs, Str255 s)
  678. {
  679.     Handle    h = NULL;
  680.     Ptr        p = NULL;
  681.     
  682.     h = HostNewHandle(procs, s[0]);
  683.     if (h != NULL)
  684.     {
  685.         p = HostLockHandle(procs, h, FALSE);
  686.         if (p != NULL)
  687.             HostCopy(p, &s[1], s[0]);
  688.         HostUnlockHandle(procs, h);
  689.     }
  690.     return h;
  691. }
  692. /*****************************************************************************/
  693. Handle HostHandleCat(HandleProcs *procs, Handle h1, Handle h2)
  694. {
  695.     int32    len1 = HostGetHandleSize(procs, h1);
  696.     int32    len2 = HostGetHandleSize(procs, h2);
  697.     Ptr        p1 = NULL;
  698.     Ptr        p2 = NULL;
  699.     
  700.     if (h1 == NULL)
  701.         h1 = HostNewHandle(procs, len2);
  702.     if (h1 != NULL && len2 > 0)
  703.     {
  704.         HostSetHandleSize(procs, h1, len1 + len2);
  705.         
  706.         p1 = HostLockHandle(procs, h1, FALSE);
  707.         p2 = HostLockHandle(procs, h2, FALSE);
  708.         
  709.         if (p1 != NULL && p2 != NULL)
  710.             HostCopy(&p1[len1], p2, len2);
  711.         
  712.         HostUnlockHandle(procs, h1);
  713.         HostUnlockHandle(procs, h2);
  714.     }
  715.     return h1;
  716. }
  717. /*****************************************************************************
  718.  * This routine uses the generic PIGetResource to grab a resource and stuff
  719.  * it into a string.  The resource will be truncated if over 255 characters.
  720.  */
  721.  
  722. void HostGetString (Handle hDllInstance, Str255 s, int32 index)
  723. {
  724.     int32    size = 0;
  725.     Ptr        p = HostGetResource(hDllInstance, StringResource, index, &size);
  726.     
  727.     s[ (s[0] = 0)+1 ] = 0;
  728.     
  729.     if (p != NULL)
  730.     {
  731.         if (size > 1) AppendString(s, (unsigned char *)p, 1, (short)(size - 1));
  732.         PIReleaseResource(p);
  733.     }
  734. }
  735. /*****************************************************************************/
  736. // Convert int32 restype to 4 characters
  737. void PIType2Char (const ResType type, char *name)
  738. {
  739.     short x;
  740.     
  741.     for (x = 3; x >= 0; x--)
  742.     {
  743.         name[x] = (char) (type & 0x000000FF);
  744.         type >>= 8;
  745.     }
  746. }
  747. /*****************************************************************************/
  748. // Convert 4 characters to int32 restype
  749. ResType PIChar2Type (char *name)
  750. {
  751.     short x;
  752.     ResType type = name[0];
  753.     
  754.     for (x = 1; x < 4; x++)
  755.     {
  756.         type <<= 8;
  757.         type += name[x];
  758.     }
  759.     return type;
  760. }
  761. /*****************************************************************************/
  762. Ptr    HostGetResource (Handle hDllInstance, ResType type, int32 index, int32 *size)
  763. {
  764.     Handle            h2 = NULL; // HGLOBAL Handle h;
  765.     Handle            h1 = NULL;    // HRSRC Handle hr;
  766.     Handle            h = NULL;
  767.     short            x = 3;
  768.     Ptr                p = NULL; // LPVOID Ptr hPtr;
  769.     char            *id = "#\0";
  770.     char            name[5] = "\0\0\0\0";
  771.     char            *s = "";
  772.     
  773.     *size = 0;
  774. #if MSWindows
  775.     if (type == StringResource)
  776.     {
  777.         char    buff[256];
  778.         
  779.         *size = LoadString(hDllInstance, index, buff, 256);
  780.         if (*size > 0)
  781.         { // got something
  782.             (*size)++; // add one for pascal length byte
  783.             h = NewHandle(*size);
  784.             if (h != NULL)
  785.             {
  786.                 HLock(h);
  787.                 memcpy(*h+1, buff, (*size)-1);
  788.                 *h[0] = (char)(*size);
  789.                 p = *h;
  790.             }
  791.         }
  792.     }
  793.     else
  794.     {
  795.         ltoa (index, s, 10);
  796.         strcat (id, s);
  797.         PIType2Char(type, &name[0]);
  798.         h1 = FindResource(hDllInstance, id, name);
  799.         if (h1 != NULL)
  800.         {
  801.             h2 = LoadResource(hDllInstance, h1);
  802.             
  803.             if (h2 != NULL)
  804.                 {
  805.                 p = LockResource(h2);
  806.     
  807.                 if (p != NULL)
  808.                 {
  809.                     *size = SizeofResource(hDllInstance, h1);
  810.     
  811.                 }
  812.             }
  813.         }
  814.     }
  815. #else // Mac
  816.     h = GetResource(type, index);
  817.     HNoPurge(h);
  818.     HLockHi(h); // lock and move high
  819.     *size = GetHandleSize(h);
  820.     p = *h; // want to return a ptr
  821. #endif
  822.     return p;
  823. }
  824. /*****************************************************************************/
  825. void PIReleaseResource(Ptr p)
  826. {
  827. #if MSWindows
  828.     // Win32 does not require FreeResource nor UnlockResource
  829. #else // Mac
  830.     if (p != NULL)
  831.     {
  832.         Handle h = RecoverHandle(p); // get that handle back
  833.         if (h != NULL)
  834.         {
  835.             HUnlock(h);
  836.             HPurge(h);
  837.             ReleaseResource(h);
  838.             h = NULL;
  839.         }
  840.     }
  841.     p = NULL;
  842. #endif
  843. }
  844. /*****************************************************************************/
  845. Boolean HostPropertyAvailable (PropertyProcs *procs, Boolean *tooNew)
  846.     {
  847.     
  848.     Boolean available = TRUE;
  849.     Boolean myTooNew = FALSE;
  850.     
  851.     if (!procs)
  852.         available = FALSE;
  853.         
  854.     else if (procs->propertyProcsVersion < kCurrentPropertyProcsVersion)
  855.         available = FALSE;
  856.         
  857.     else if (procs->propertyProcsVersion > kCurrentPropertyProcsVersion)
  858.         {
  859.         available = FALSE;
  860.         myTooNew = TRUE;
  861.         }
  862.         
  863.     else if (!procs->getPropertyProc ||
  864.              !procs->setPropertyProc)
  865.         available = FALSE;
  866.         
  867.     if (tooNew)
  868.         *tooNew = myTooNew;
  869.         
  870.     return available;
  871.     
  872.     }
  873. /*****************************************************************************/
  874. Boolean WarnHostPropertyAvailable (PropertyProcs *procs,
  875.                                    Handle hDllInstance)
  876. {
  877.     
  878.     Boolean available, tooNew;
  879.     Str255 s = "";
  880.     
  881.     available = HostPropertyAvailable (procs, &tooNew);
  882.     
  883.     if (!available)
  884.     {
  885.         DoubleToString(2.5, s, 1);
  886.         ShowVersionAlert (hDllInstance,
  887.                           NULL,
  888.                           AlertID,
  889.                           (short)(tooNew ? kWrongHost : kNeedVers),
  890.                           s,
  891.                           NULL);
  892.     }
  893.     return available;    
  894. }
  895. /*****************************************************************************/
  896. Boolean HostChannelPortAvailable (ChannelPortProcs *procs, Boolean *tooNew)
  897.     {
  898.     
  899.     Boolean available = TRUE;
  900.     Boolean myTooNew = FALSE;
  901.     
  902.     if (!procs)
  903.         available = FALSE;
  904.         
  905.     else if (procs->channelPortProcsVersion < kCurrentChannelPortProcsVersion)
  906.         available = FALSE;
  907.         
  908.     else if (procs->channelPortProcsVersion > kCurrentChannelPortProcsVersion)
  909.         {
  910.         
  911.         available = FALSE;
  912.         
  913.         myTooNew = TRUE;
  914.         
  915.         }
  916.         
  917.     else if (procs->numChannelPortProcs < kCurrentChannelPortProcsCount ||
  918.              !procs->readPixelsProc ||
  919.              !procs->writeBasePixelsProc ||
  920.              !procs->readPortForWritePortProc)
  921.         available = FALSE;
  922.         
  923.     if (tooNew)
  924.         *tooNew = myTooNew;
  925.         
  926.     return available;
  927.     
  928.     }
  929. /*****************************************************************************/
  930. Boolean WarnHostChannelPortAvailable (ChannelPortProcs *procs,
  931.                                       Handle hDllInstance)
  932. {
  933.     
  934.     Boolean available, tooNew;
  935.     Str255 s = "";
  936.     
  937.     available = HostChannelPortAvailable (procs, &tooNew);
  938.     
  939.     if (!available)
  940.     {
  941.         DoubleToString(2.5, s, 1);
  942.         ShowVersionAlert (hDllInstance,
  943.                           NULL,
  944.                           AlertID,
  945.                           (short)(tooNew ? kWrongHost : kNeedVers),
  946.                           s,
  947.                           NULL);
  948.     }
  949.     return available;    
  950. }
  951. /*****************************************************************************/
  952. Boolean HostDescriptorAvailable (PIDescriptorParameters *procs, Boolean *tooNew)
  953.     {
  954.     
  955.     Boolean available = TRUE;
  956.     Boolean myTooNew = FALSE;
  957.     
  958.     if (!procs)
  959.         available = FALSE;
  960.         
  961.     else if (procs->descriptorParametersVersion < 
  962.              kCurrentDescriptorParametersVersion)
  963.         available = FALSE;
  964.         
  965.     else if (procs->descriptorParametersVersion >
  966.              kCurrentDescriptorParametersVersion)
  967.         {
  968.         
  969.         available = FALSE;
  970.         
  971.         myTooNew = TRUE;
  972.         
  973.         }
  974.         
  975.     else if (!procs->readDescriptorProcs || 
  976.              !procs->writeDescriptorProcs)
  977.         available = FALSE;
  978.         
  979.     else if (procs->readDescriptorProcs->readDescriptorProcsVersion
  980.              < kCurrentReadDescriptorProcsVersion ||
  981.              procs->readDescriptorProcs->numReadDescriptorProcs
  982.              < kCurrentReadDescriptorProcsCount ||
  983.              procs->writeDescriptorProcs->writeDescriptorProcsVersion
  984.              < kCurrentWriteDescriptorProcsVersion ||
  985.              procs->writeDescriptorProcs->numWriteDescriptorProcs
  986.              < kCurrentWriteDescriptorProcsCount)
  987.         available = FALSE;
  988.         
  989.     if (tooNew)
  990.         *tooNew = myTooNew;
  991.         
  992.     return available;
  993.     
  994.     }
  995. /*****************************************************************************/
  996. Boolean WarnHostDescriptorAvailable (PIDescriptorParameters *procs,
  997.                                      Handle hDllInstance)
  998. {
  999.     
  1000.     Boolean available, tooNew;
  1001.     Str255 s = "";
  1002.     
  1003.     available = HostDescriptorAvailable (procs, &tooNew);
  1004.     
  1005.     if (!available)
  1006.     {
  1007.         DoubleToString(2.5, s, 1);
  1008.         ShowVersionAlert (hDllInstance,
  1009.                           NULL,
  1010.                           AlertID,
  1011.                           (short)(tooNew ? kWrongHost : kNeedVers),
  1012.                           s,
  1013.                           NULL);
  1014.     }
  1015.     return available;
  1016. }
  1017. /*****************************************************************************/
  1018. /* Closes read descriptor and disposes handle. */
  1019. OSErr HostCloseReader (PIDescriptorParameters *procs,
  1020.                        HandleProcs *hProcs,
  1021.                        PIReadDescriptor *token)
  1022. {
  1023.     OSErr        err = noErr;
  1024.     
  1025.     err = procs->readDescriptorProcs->closeReadDescriptorProc(*token);
  1026.     HostDisposeHandle(hProcs, procs->descriptor);
  1027.     procs->descriptor = NULL;
  1028.     *token = NULL;
  1029.     
  1030.     return err;
  1031. }
  1032. /*****************************************************************************/
  1033. /* Closes write descriptor.  Disposes old handle, if present, and sets
  1034.    recordInfo to plugInDialogOptional. */
  1035. OSErr    HostCloseWriter(PIDescriptorParameters *procs,
  1036.                         HandleProcs *hProcs,
  1037.                         PIWriteDescriptor *token)
  1038. {
  1039.     OSErr                err = noErr;
  1040.     PIDescriptorHandle    h = NULL;
  1041.     
  1042.     if (procs->descriptor) // don't need descriptor passed to us
  1043.         HostDisposeHandle(hProcs, procs->descriptor); // dispose.
  1044.     procs->writeDescriptorProcs->closeWriteDescriptorProc(*token, &h);
  1045.     procs->descriptor = h;
  1046.     procs->recordInfo = plugInDialogOptional;
  1047.         /* most likely.  Otherwise:  plugInDialogOptional ||
  1048.                                      plugInDialogRequire ||
  1049.                                      plugInDialogNone */
  1050.     *token = NULL;
  1051.     
  1052.     return err;
  1053. }
  1054. /*****************************************************************************/
  1055. /* Puts an object and disposes its handle, returning any error. */
  1056. OSErr HostPutObj (PIDescriptorParameters *procs, HandleProcs *hProcs, 
  1057.                   PIWriteDescriptor desc, DescriptorKeyID key, DescriptorTypeID type,
  1058.                   PIDescriptorHandle *h)
  1059. {
  1060.     OSErr        err = noErr;
  1061.     
  1062.     err = procs->writeDescriptorProcs->putObjectProc(desc, key, type, *h);
  1063.     HostDisposeHandle(hProcs, *h);
  1064.     *h = NULL;
  1065.     return err;
  1066. }
  1067. /*****************************************************************************/
  1068. /* Returns whether playInfo is plugInDialogDisplay, meaning to absolutely pop
  1069.    the plug-in dialog. */
  1070.    
  1071. Boolean    HostPlayDialog(PIDescriptorParameters *procs)
  1072. {
  1073.     return procs->playInfo == plugInDialogDisplay;
  1074.     /* plugInDialogDontDisplay = display if necessary,
  1075.        plugInDialogDisplay = display,    
  1076.        plugInDialogSilent = never display */
  1077. }
  1078. /*****************************************************************************/
  1079. /* This routine divides a string at its decimal point. */
  1080. void DivideAtDecimal(Str255 s1, Str255 s2)
  1081.     short    loop = s1[0];
  1082.     
  1083.     do
  1084.     {
  1085.         if (s1[loop] == '.')
  1086.         {
  1087.             AppendString(s2, s1, (short)(loop+1), (short)(s1[0] - loop));
  1088.             s1[ 1+ (s1[0]=loop-1) ] = 0;
  1089.             loop = 1;
  1090.         }
  1091.         loop--;
  1092.     }
  1093.     while (loop > 0);
  1094. }
  1095.     
  1096. /*****************************************************************************/
  1097. /* The following routine appends one string to another. */
  1098. void AppendString (Str255 s1, Str255 s2, short start, short length)
  1099. {
  1100.     if ( (s1[0] + (length - start)) > 255) length = (255 + start) - s1[0];
  1101.     for ( ; length > 0; length--)
  1102.         s1[ ++s1[0] ] = s2[start++];
  1103. }
  1104. void AppendCharToString (Str255 s1, const unsigned char c)
  1105. {
  1106.     if (s1[0] < 256) s1[ ++s1[0] ] = c;
  1107. }
  1108. /*****************************************************************************/
  1109. void HostBlockMove (Ptr p1, Ptr p2, const int32 amount)
  1110. {
  1111.     if (p1 != NULL && p2 != NULL)
  1112.     {
  1113.         for ( ; amount > 0; amount--)
  1114.             *(p1++) = *(p2++);
  1115.     }
  1116. }
  1117. /*****************************************************************************/
  1118. void HostCopy (void *s1, const void *s2, const int32 amount)
  1119. {
  1120.     HostBlockMove((Ptr)s1, (Ptr)s2, amount);
  1121. }        
  1122. /*****************************************************************************/
  1123. int16 HostStringCat (char *s1, const char *s2)
  1124. {
  1125.     int16    x = HostMatch(s1, "\0", false);
  1126.     int16    loop = 0;
  1127.     
  1128.     if (x < 0) x = 0; // no match, blast at beginning
  1129.     while (x < 256 && s2[loop] != 0)
  1130.         s1[x++] = s2[loop++];
  1131.     s1[x] = 0;
  1132.     return x;
  1133. }
  1134. /*****************************************************************************/
  1135. int16 HostStringMatch(Str255 s1, const char *s2, Boolean ignoreCase)
  1136. {
  1137.     if (s1[0] < 255)
  1138.     { // null terminate
  1139.         s1[ s1[0]+1 ] = 0;
  1140.         // s2[ s1[0]+1 ] = 0;
  1141.     }
  1142.     return HostMatch((char *)s1, s2, ignoreCase);
  1143. }
  1144. /*****************************************************************************/
  1145. char UpperToLower(const char c1)
  1146. {
  1147.     char    retn = c1;
  1148.     
  1149.     if (c1 >= 'A' && c1 <= 'Z')
  1150.         retn = (c1-'A') + 'a';
  1151.     return retn;
  1152. }
  1153.     
  1154. /*****************************************************************************/
  1155. int16 HostMatch(char *s1, const char *s2, Boolean ignoreCase)
  1156. {
  1157.     int16    loop = 0;
  1158.     int16    start = 0;
  1159.     int16    retn = noMatch; // -1 = no match
  1160.     
  1161.     do
  1162.     {
  1163.         if (s1[loop] == s2[start] || 
  1164.             (ignoreCase && (UpperToLower(s1[loop]) == UpperToLower(s2[start]))))
  1165.         {
  1166.             if (retn < 0) retn = loop;
  1167.             start++;
  1168.         }
  1169.         
  1170.         else
  1171.         {
  1172.             retn = noMatch;
  1173.             start = 0; // reset
  1174.         }
  1175.     } while (s1[loop++] > 0 && loop < 256);
  1176.     
  1177.     if (s1[loop-1] > 0) retn = noMatch; // didn't match exactly
  1178.     return retn;
  1179. }        
  1180. /*****************************************************************************/
  1181. /* Turns a double into a string. */
  1182. void DoubleToString (double value, Str255 s, short precision)
  1183. {
  1184.     unsigned32    x = 0;
  1185.     double        y = 0;
  1186.     
  1187.     s[ (s[0]=0)+1 ] = 0;
  1188.     
  1189.     // determine if we need to round:
  1190.     y = value * power(10, precision);
  1191.     x = (unsigned32)y; // whole portion;
  1192.     y -= x; // subtract whole portion
  1193.     y *= 10; // move over one more place
  1194.     if (y >= 5) value += (5.0 / (double)power(10, (short)(precision+1)));
  1195.     
  1196.     if (precision > 1)
  1197.     { // now check to see if we can lose a decimal place
  1198.         y = value * power(10, (short)(precision-1));
  1199.         x = (unsigned32)y; // whole portion
  1200.         y -= x; // subtract whole portion
  1201.         y *= 10; // number of interest
  1202.         if (y < 1) precision--;
  1203.         // our number of interest is zero, so lose a point of precision
  1204.     }
  1205.     y = 0; // done with this
  1206.     
  1207.     x = (unsigned32)value;
  1208.     
  1209.     NumToString((long)x, s);
  1210.     s[++s[0]] = '.';
  1211.     value -= x; // get rid of whole-number portion
  1212.     do
  1213.     {
  1214.         value *= 10;
  1215.         x = (unsigned32)value; // whole number
  1216.         s[++s[0]] = '0' + (char)(x);
  1217.         value -= x;
  1218.     }
  1219.     while (value > 0 && --precision > 0);
  1220. }
  1221. /*****************************************************************************/
  1222. /* Raises a base to a power */
  1223. double power (long base, short raise)
  1224. {
  1225.     double p = 1;
  1226.     
  1227.     for ( ; raise > 0; raise--)
  1228.         p *= base;
  1229.     return p;
  1230. }
  1231. /*****************************************************************************/
  1232. Boolean StringToNumber (Str255 s, long *value)
  1233.     {
  1234.     
  1235.     short i;
  1236.     short j;
  1237.     long x;
  1238.     Boolean negative = FALSE;
  1239.     Boolean isNumber = TRUE;
  1240.     Boolean trailingBlanks = FALSE;
  1241.     
  1242.     for (i = 1, j = 0; i <= s[0] && isNumber; ++i)
  1243.         {
  1244.         
  1245.         if (j == 0 && s [i] == ' ')
  1246.             ; /* Do nothing: Leading blanks */
  1247.             
  1248.         else if (j > 0 && s [i] == ' ')
  1249.             trailingBlanks = TRUE;
  1250.             
  1251.         else if (trailingBlanks && s [i] != ' ')
  1252.             isNumber = FALSE;
  1253.             
  1254.         else if (j == 0 && !negative && s [i] == '-')
  1255.             negative = TRUE;
  1256.             
  1257.         else if (s [i] < '0' || s [i] > '9')
  1258.             isNumber = FALSE;
  1259.             
  1260.         else
  1261.             s [++j] = s [i];
  1262.         
  1263.         }
  1264.         
  1265.     if (j == 0)
  1266.         isNumber = FALSE;
  1267.     else
  1268.         s[ (s[0] = (char) j)+1] = 0;
  1269.     
  1270.     if (isNumber)
  1271.         {
  1272.         
  1273.         if (j <= 9)
  1274. #if MSWindows
  1275.             x = atol(&s[1]);
  1276. #else // Mac
  1277.             StringToNum (s, &x);
  1278. #endif
  1279.             else
  1280.             x = 0x7FFFFFFF;
  1281.         
  1282.         if (negative)
  1283.             x = -x;
  1284.             
  1285.         *value = x;
  1286.             
  1287.         }
  1288.         
  1289.     return isNumber;
  1290.     
  1291.     }
  1292.     
  1293. /*********************************************************************/
  1294. void PIParamText(unsigned char *s, unsigned char *r0, unsigned char *r1, unsigned char *r2)
  1295. {
  1296.     short    loop = 0;
  1297.     Boolean    flag = false;
  1298.     Str255 s1 = "";
  1299.     Str255 rx = "";
  1300.     
  1301.     while (loop < s[0])
  1302.     {
  1303.         loop++;
  1304.         
  1305.         if (s[loop] == '^') flag = true;
  1306.         else if (s[loop] >= '0' && s[loop] <= '2' && flag)
  1307.         {
  1308.             flag = false;
  1309.             switch(s[loop])
  1310.             {
  1311.                 case '0':
  1312.                     if (r0) AppendString(rx, r0, 1, (short)(r0[0]));
  1313.                     else rx[ (rx[0] = 0)+1 ] = 0;
  1314.                     break;
  1315.                 case '1':
  1316.                     if (r1) AppendString(rx, r1, 1, (short)(r1[0]));
  1317.                     else rx[ (rx[0] = 0)+1 ] = 0;
  1318.                     break;
  1319.                 case '2':
  1320.                     if (r2) AppendString(rx, r2, 1, (short)(r2[0]));
  1321.                     else rx[ (rx[0] = 0)+1 ] = 0;
  1322.                     break;
  1323.             }
  1324.             
  1325.             if (rx)
  1326.             {
  1327.                 AppendString(s1, s, 1, (short)(loop-2));
  1328.                 AppendString(s1, rx, 1, (short)rx[0]);
  1329.                 AppendString(s1, s, (short)(loop+1), (short)(s[0]-loop));
  1330.                 s[0] = 0;
  1331.                 AppendString(s, s1, 1, s1[0]);
  1332.                 s1[ (s1[0]=0)+1 ] = 0;
  1333.                 rx[ (rx[0]=0)+1 ] = 0;
  1334.                 loop--; // stay here to check for other ^x's.
  1335.             }
  1336.         }
  1337.         else flag = false;
  1338.     }
  1339. }
  1340.           
  1341. /*********************************************************************/
  1342. short HostReportError(Str255 s1, Str255 s2)
  1343. {
  1344.     if (s1)
  1345.     {
  1346.         s1[ (s1[0]=0)+1 ] = 0;
  1347.         AppendString(s1, s2, 1, s2[0]);
  1348.     }
  1349.     else s1 = s2;
  1350.     return errReportString;
  1351. }
  1352. /*********************************************************************/
  1353. void GetOSInfo(HandleProcs *procs, OSInfo *osInfo)
  1354. {
  1355. #if MSWindows
  1356.  
  1357.     DWORD        lpdwHandle;     // pointer to variable to receive zero
  1358.     char        *lpBuffer[80];    // address of buffer for version pointer
  1359.     char        lpFilename[256];
  1360.     int32        len = 0;
  1361.     char        lpData[1024]; // enough for what we need
  1362.     VS_FIXEDFILEINFO    *ffi;
  1363.     DWORD        x = 0;
  1364.     Ptr            p = 0;
  1365.     Str255        s1 = "", s2 = "";
  1366.     len = GetModuleFileName(NULL /* hDllInstance */, lpFilename, 255);
  1367.     len = GetFileVersionInfoSize(lpFilename, &lpdwHandle);
  1368.     GetFileVersionInfo(lpFilename, lpdwHandle, 1024, lpData);
  1369.  
  1370.     VerQueryValue(lpData, TEXT("\\"), lpBuffer, &len); // ask for basic info
  1371.     p = *(lpBuffer);
  1372.     ffi = (VS_FIXEDFILEINFO *)p;
  1373.     osInfo->stage = MapStage(ffi->dwFileFlagsMask, ffi->dwFileFlags); // release, prerelease, etc.
  1374.     osInfo->stageVersion = 0;
  1375.     osInfo->os = MapSystem(ffi->dwFileOS);
  1376.   
  1377.     VerQueryValue(lpData, 
  1378.                   TEXT("\\StringFileInfo\\040904E4\\InternalName"),
  1379.                   lpBuffer,
  1380.                   &len);
  1381.     p = *lpBuffer; // returns a ptr to the string
  1382.     osInfo->signature = MapSignature(p);
  1383.  
  1384.     VerQueryValue(lpData,
  1385.                   TEXT("\\StringFileInfo\\040904E4\\FileVersion"),
  1386.                   lpBuffer,
  1387.                   &len);
  1388.     p = *lpBuffer; // returns a ptr to the string
  1389.     AppendString(s1, (unsigned char *)p, 0, (short)strlen(p)); // copy string to pascal
  1390.     DivideAtDecimal(s1, s2);
  1391.     StringToNumber(s1, &x);
  1392.     osInfo->majorVersion = (unsigned8)x;
  1393.  
  1394.     x = 0; // just in case
  1395.     StringToNumber(s2, &x);
  1396.     osInfo->minorVersion = (unsigned8)x;
  1397.  
  1398.     osInfo->subVersion = 0;
  1399.  
  1400. #else // Macintosh/Unix
  1401.     short    rID;
  1402.     Handle    h = NULL;
  1403.     Ptr        p = NULL;
  1404.     long    x;
  1405.         
  1406.     rID = CurResFile(); // get the current resource file
  1407.     
  1408.     UseResFile( LMGetCurApRefNum() ); // sets the res file to the application (not the plug-in)
  1409.     
  1410.     h = Get1IndResource('BNDL', 1); // want the 1st bndl resource of the app
  1411.     
  1412.     if (!ResError())
  1413.     { // work with bndl
  1414.         p = HostLockHandle(procs, h, FALSE);
  1415.         if (p != NULL)
  1416.         {
  1417.             osInfo->signature = PIChar2Type(p);
  1418.         }
  1419.         
  1420.         HostUnlockHandle(procs, h);
  1421.         ReleaseResource(h);
  1422.         h = NULL;
  1423.         p = NULL;
  1424.     }
  1425.         
  1426.     h = Get1IndResource('vers', 1); // want the 1st vers resource of the app
  1427.         
  1428.     if (!ResError())
  1429.     {
  1430.         
  1431.         p = HostLockHandle(procs, h, FALSE);
  1432.         if (p != NULL)
  1433.         {
  1434.             osInfo->majorVersion = (unsigned8)*p++;
  1435.             osInfo->minorVersion = osInfo->subVersion = (unsigned8)*p++;
  1436.             osInfo->minorVersion >>= 4; // top 4 bits = vers2
  1437.             osInfo->subVersion &= 0x0F; // bottom 4 bits = vers3
  1438.             osInfo->stage = MapStage(NULLID,(unsigned32)*p++); // 0x20 = dev,
  1439.                               // 0x40 = alpha,
  1440.                               // 0x60 = beta,
  1441.                               // 0x80 = release
  1442.             osInfo->stageVersion = (unsigned8)*p;
  1443.         }
  1444.         HostUnlockHandle(procs, h);
  1445.         ReleaseResource(h);
  1446.         h = NULL;
  1447.         p = NULL;
  1448.     }
  1449.     
  1450.     if (Gestalt(gestaltSystemVersion, &x) == noErr)
  1451.     { // got the system version.
  1452.         osInfo->os = MapSystem((unsigned32)(x >> 8));
  1453.     }
  1454.     UseResFile (rID);
  1455. #endif // Mac/Unix
  1456. /*********************************************************************/
  1457. unsigned32 AppMatch (HandleProcs *procs, ResType *type)
  1458. {
  1459.     ResType        *p    = type;
  1460.     Boolean        gotit = false;
  1461.     unsigned32     retn = 0;
  1462.     OSInfo        osInfo;
  1463.     
  1464.     GetOSInfo(procs, &osInfo);
  1465.     
  1466.     while (*p != NULLID && gotit == false)
  1467.         gotit = (*p++ == osInfo.signature);
  1468.         
  1469.     if (gotit)
  1470.         retn = (osInfo.majorVersion << 24) |
  1471.                (osInfo.minorVersion << 16) |
  1472.                (osInfo.os);
  1473.     return retn;
  1474. }
  1475. /*********************************************************************/
  1476. unsigned32 HostHostIsApp (HandleProcs *procs, const ResType type)
  1477. {
  1478.     const ResType types[] = { rtAfterEffects, NULLID,
  1479.                              rtIllustrator, NULLID,
  1480.                              rtPageMaker5, rtPageMaker6, rtPageMaker65, NULLID,
  1481.                              rtPhotoDeluxe, NULLID,
  1482.                              rtPhotoshop, NULLID,
  1483.                              rtPremiere, NULLID };
  1484.     
  1485.     const short    numResTypes = sizeof(types) / sizeof(ResType);
  1486.     
  1487.     short loop = 0;
  1488.     unsigned32    retn = 0;
  1489.     
  1490.     do
  1491.     {
  1492.         if (types[loop] == type && types[loop] != NULLID)
  1493.         { // got a match
  1494.             retn = AppMatch(procs, &types[loop]);
  1495.             loop = numResTypes; // done looping
  1496.         }
  1497.     } while (++loop < numResTypes);
  1498.     
  1499.     return retn;
  1500. }
  1501.  
  1502. /*********************************************************************/
  1503. unsigned8    MapStage (const unsigned32 stageMask, const unsigned32 stage)
  1504.  
  1505. {
  1506. #if MSWindows
  1507.     if (stageMask & 0x01L && stage & 0x01L)
  1508.         return OSStageDevelopment; // 0x01L = VS_FF_DEBUG
  1509.     else if (stageMask & 0x02L && stage & 0x02L)
  1510.         return OSStageBeta; // 0x02L = VS_FF_PRERELEASE
  1511.     else return OSStageRelease;
  1512.     
  1513. #else // Mac/Unix
  1514.  
  1515.     switch (stage)
  1516.     {
  1517.         case 0x20:
  1518.             return OSStageDevelopment;
  1519.             break;
  1520.         case 0x40:
  1521.             return OSStageAlpha;
  1522.             break;
  1523.         case 0x60:
  1524.             return OSStageBeta;
  1525.             break;
  1526.         case 0x80:
  1527.         default:
  1528.             return OSStageRelease;
  1529.             break;
  1530.     }
  1531. #endif
  1532. }
  1533.  
  1534. /*********************************************************************/
  1535. unsigned8    MapSystem (const unsigned32 os)
  1536. {
  1537. #if MSWindows
  1538.     switch (os)
  1539.     {
  1540.         case 0x00040000L:
  1541.             return OSWinNT;
  1542.             break;
  1543.         case 0x01L:
  1544.             return OSWin16;
  1545.             break;
  1546.         case 0x04L:
  1547.         default:
  1548.             return OSWin32;
  1549.             break;
  1550.     }
  1551. #else // Mac/Unix
  1552.     switch (os)
  1553.     {
  1554.         case 6:
  1555.             return OSMacOS6;
  1556.             break;
  1557.         case 8:
  1558.             return OSMacOS8;
  1559.             break;
  1560.         case 7:
  1561.         default:
  1562.             return OSMacOS7;
  1563.             break;
  1564.     }
  1565. #endif
  1566. }
  1567. /*********************************************************************/
  1568.  
  1569. unsigned32    MapSignature (char *s1)
  1570. {
  1571.     const char   *fileNames[] = { fnAfterEffects,
  1572.                                   fnIllustrator,
  1573.                                   fnPageMaker5,
  1574.                                   fnPageMaker6,
  1575.                                   fnPageMaker65,
  1576.                                   fnPhotoDeluxe,
  1577.                                   fnPhotoshop,
  1578.                                   fnPremiere };
  1579.     const ResType fileTypes[] = { rtAfterEffects,
  1580.                                   rtIllustrator,
  1581.                                   rtPageMaker5,
  1582.                                   rtPageMaker6,
  1583.                                   rtPageMaker65,
  1584.                                   rtPhotoDeluxe,
  1585.                                   rtPhotoshop,
  1586.                                   rtPremiere };
  1587.  
  1588.     const short numResTypes = sizeof(fileTypes) / sizeof(ResType);
  1589.  
  1590.     unsigned32 retn = NULLID;
  1591.  
  1592.     short loop = 0;
  1593.  
  1594.     do
  1595.     {
  1596.         if (HostMatch(s1, fileNames[loop], true) == gotMatch)
  1597.         { // got a match
  1598.             retn = fileTypes[loop];
  1599.             loop = numResTypes;
  1600.         }
  1601.     } while (++loop < numResTypes);
  1602.  
  1603.     return retn;
  1604.  
  1605. }
  1606.  
  1607. /*********************************************************************/
  1608.  
  1609. Boolean        IsWindows (const unsigned32 flag)
  1610. {
  1611.     unsigned8 smallFlag = (unsigned8)(flag & 0xFF); // take lowest byte
  1612.     
  1613.     if (smallFlag >= OSWin1 && smallFlag <= OSWinEnd)
  1614.         return true;
  1615.     else return false;
  1616. }
  1617. /*********************************************************************/
  1618.  
  1619. Boolean        IsMacOS (const unsigned32 flag)
  1620. {
  1621.     unsigned8 smallFlag = (unsigned8)(flag & 0xFF); // take lowest byte
  1622.     
  1623.     if (smallFlag >= OSMacOS1 && smallFlag <= OSMacOSEnd)
  1624.         return true;
  1625.     else return false;
  1626. }
  1627. /*********************************************************************/
  1628.